package com.acoreful.ackitcloud.route;

import cn.hutool.core.collection.CollectionUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.util.List;

@Component
@Slf4j
@RequiredArgsConstructor
public class DynamicRouteManger implements ApplicationEventPublisherAware {

    private final RouteDefinitionWriter routeDefinitionWriter;
    private final RouteDefinitionLocator routeDefinitionLocator;
    private ApplicationEventPublisher publisher;
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher=applicationEventPublisher;
    }

    /**
     * 增加路由
     * @param definition
     */
    public boolean add(RouteDefinition definition){
        this.routeDefinitionWriter.save(Mono.just(definition)).subscribe();
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
        return true;
    }

    /**
     * 更新路由
     * @param definition
     */
    public boolean updateById(RouteDefinition definition){
        this.routeDefinitionWriter.delete(Mono.just(definition.getId()));
        this.add(definition);
        return true;
    }

    /**
     * 更新路由
     * @param routeDefinitions
     */
    public boolean batchUpdate(List<RouteDefinition> routeDefinitions){
        if(CollectionUtil.isEmpty(routeDefinitions)){
            return true;
        }
        //清理缓存
        List<RouteDefinition> routeDefinitionsExits=routeDefinitionLocator.getRouteDefinitions().buffer().blockFirst();
        if (CollectionUtil.isNotEmpty(routeDefinitionsExits)) {
            routeDefinitionsExits.forEach(routeDefinition -> deleteById(routeDefinition.getId()));
        }
        //更新
        routeDefinitions.forEach(this::updateById);
        return true;
    }


    /**
     * 删除路由
     * @param id
     */
    public boolean deleteById(String id){
        this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
        return true;
    }
}
